#include "IslandApp.h"
#include <fstream>
#include "Refractor.h"
using std::ifstream;

float		glb_Val;
float		glb_waveAngle;
float		glb_WorldRadius					= 6.5f;
std::string glb_strSeason				= "Spring";
float		glb_windPower					= 0.5f;
float		dir[3] = {1, 0, 0}; // 

bool		glb_fixedView			= false;
float		glb_minTriangleArea		= 0.0f;
float		glb_maxTriangleArea		= 0.6f;
UINT		glb_minTriSamples		= 8;
UINT		glb_maxTriSamples		= 10;
XMFLOAT3	glb_windDir				= XMFLOAT3(1,0,0);

// Main message loop
int IslandApp::run() {

	DXApp::startTimer();

	MSG msg = {0};
	while (WM_QUIT != msg.message) 
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		} 
		else 
		{
			if (bEnd)
				return 0;

			float step = 0.05f;
			float step_view = 0.025f;

			if(GetAsyncKeyState(0x26) & 0x8000) camera.rotateX(-step_view);	// up
			if(GetAsyncKeyState(0x28) & 0x8000) camera.rotateX(+step_view);	// down
			if(GetAsyncKeyState(0x25) & 0x8000) camera.rotateY(-step_view);		// left
			if(GetAsyncKeyState(0x27) & 0x8000) camera.rotateY(+step_view);		// right

			if (GetAsyncKeyState('W') & 0x8000) camera.walkForward(+step);
			if (GetAsyncKeyState('S') & 0x8000) camera.walkForward(-step);
			if (GetAsyncKeyState('A') & 0x8000) camera.walkSide(-step);
			if (GetAsyncKeyState('D') & 0x8000) camera.walkSide(+step);			


			updateScene();
			renderScene(dt);
		}
	}

	TwTerminate();
	
	return (int)msg.wParam;
}




IslandApp::IslandApp() :DXApp(), sim_speed(1), bEnd(false), _season(SPRING), _day(0), day_time(0.0), season_time(0.0),
						day_length(10.0), season_length(20.0), 
							fx(0), fx_shadow(0), fx_quad(0), input_layout(0), vb_quad(0), dt(0.0f), mEditMode(false)
{
	_lights.reserve(4);
}

IslandApp::~IslandApp() 
{

	try
	{
		if (fx) fx->Release();
		if (fx_shadow) fx_shadow->Release();
		if (fx_quad) fx_quad->Release();
		if (input_layout) input_layout->Release();
		if (vb_quad) vb_quad->Release();
		if (fireSystem) delete fireSystem;
	}
	catch(...)
	{
		MessageBoxA(0, "Exception thrown in IslandApp destructor", 0, 0);
	}
}

bool IslandApp::initialise(HINSTANCE hInstance, int cmdShow) 
{
	
	readConfigFile();
	
	if (!DXApp::initialise(hInstance, cmdShow))
		return false;

	// Build FXs
	if (FAILED(buildFX())) {
		MessageBox(0, L"Cannot create effects", L"Error", MB_OK|MB_ICONERROR);
		return false;
	}
	
	// Build Geometry
	if (FAILED(buildGeometry())) {
		MessageBox(0, L"Cannot create geometry", L"Error", MB_OK|MB_ICONERROR);
		return false;
	}

	m_ViewMode = VIEW_GLOBE;
	updateViewMode();

	camera.setProjection(0.7f, _params.width/(float)_params.height, 1.0f, 50.0f);
	
	createLights();
	createInputLayout();


	fireSystem = new FireSystem();
	fireSystem->init(g_dev(), g_context(), input_layout);
	fireSystem->setAppHandle(this);

	fireSystem->addObject(&_tree);

	initGUI();

	return true;
}

void IslandApp::createLights()
{
	_lights.push_back(&(spotlights[0]));
	_lights.push_back(&(spotlights[1]));
	_lights.push_back(&(spotlights[2]));
	_lights.push_back(&(spotlights[3]));

	for (int i=0; i<4; ++i)
	{
		_lights[i]->createShadowResources(_params._shadow_texture, g_dev(), g_context());
		_lights[i]->setShadowMapEffect(fx_shadow);
	}

	directional.createShadowResources(_params._shadow_texture, g_dev(), g_context());
	directional.setShadowMapEffect(fx_shadow);
}

HRESULT IslandApp::buildFX() {
	// Load and create the pre-compiled shader code
	std::vector<char> compiledShader(0);
	
	// shaders
	if (!loadEffect("../Desert_Island/shaders/basic.fxo", compiledShader))
		MessageBoxA(0, "Error Loading Effect", 0, 0);
	
	HRESULT hr = D3DX11CreateEffectFromMemory(&compiledShader[0], compiledShader.size(), 0, g_dev(), &fx);
	if (FAILED(hr)) MessageBoxA(0, "Error creating FX", 0, 0);

	//////

	if (!loadEffect("../Desert_Island/shaders/shadow_map.fxo", compiledShader))
		MessageBoxA(0, "Error Loading shadow.fxo Effect", 0, 0);
	
	hr = D3DX11CreateEffectFromMemory(&compiledShader[0], compiledShader.size(), 0, g_dev(), &fx_shadow);
	if (FAILED(hr)) MessageBoxA(0, "Error creating shadow.fx FX", 0, 0);

	//////

	if (!loadEffect("../Desert_Island/shaders/quad.fxo", compiledShader))
		MessageBoxA(0, "Error Loading quad.fxo Effect", 0, 0);
	
	hr = D3DX11CreateEffectFromMemory(&compiledShader[0], compiledShader.size(), 0, g_dev(), &fx_quad);
	if (FAILED(hr)) MessageBoxA(0, "Error creating quad.fx FX", 0, 0);
	
	return S_OK;
}

HRESULT IslandApp::buildGeometry() 
{
	_island.init(_params.file_island.c_str(),	g_dev(), g_context());
	_globe.init(	_params.file_globe.c_str(),		g_dev(), g_context());
	_sea.init(	_params.file_sea.c_str(),	g_dev(),	g_context(), _params.width, _params.height);
	_tree.init(	_params.file_tree.c_str(),	g_dev(), g_context());
	_bottle.init( _params.file_bottle.c_str(),	g_dev(), g_context());

	_sea.setDayLength(day_length);

	_bottle.setPos(1.2f, 2.0f, -0.70f);

	///////////////////////

	Vertex v_quad[] =	{		

							{ XMFLOAT3( 1.0f,  1.0f, 0.5f), XMFLOAT3(0,0,0), XMFLOAT3(0,0,0), XMFLOAT2(0,0) },
							{ XMFLOAT3(-1.0f,  1.0f, 0.5f), XMFLOAT3(0,0,0), XMFLOAT3(0,0,0), XMFLOAT2(0,0) },
							{ XMFLOAT3( 1.0f, -1.0f, 0.5f), XMFLOAT3(0,0,0), XMFLOAT3(0,0,0), XMFLOAT2(0,0) },
							{ XMFLOAT3(-1.0f, -1.0f, 0.5f), XMFLOAT3(0,0,0), XMFLOAT3(0,0,0), XMFLOAT2(0,0) }
						};		

	D3D11_BUFFER_DESC vb_desc;
	vb_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vb_desc.ByteWidth = sizeof(Vertex) * 4;
	vb_desc.CPUAccessFlags = vb_desc.MiscFlags = 0;
	vb_desc.Usage = D3D11_USAGE_DEFAULT;

	D3D11_SUBRESOURCE_DATA vb_data;
	ZeroMemory(&vb_data, sizeof vb_data);
	vb_data.pSysMem = v_quad;
	
	HRESULT hr = g_dev()->CreateBuffer(&vb_desc, &vb_data, &vb_quad);
	if (FAILED(hr)) MessageBoxA(0, "Error creating quad buffer", 0, 0);


    return S_OK;
}

void IslandApp::updateScene() 
{
	dt = (float)DXApp::getDeltaTime();


	dt *= sim_speed * 1.0f;

	day_time += dt;
	if (day_time >= day_length) {
		day_time = 0.0;
		_day++;
	}

	season_time += dt;
	if (season_time >= season_length) {
		_season++;
		if (WINTER < _season) _season = SPRING;
		season_time = 0.0f;
		day_time = 0.0f;
		_day = 0;
	}



	updateLights(dt);

	_sea.adjustSeaLevel(day_time);



	_sea.Update(dt);
	_tree.Update(dt);
	_island.Update(dt);
	_bottle.Update(dt);
	_globe.Update(dt);

	

	if (SPRING == _season && 0 == _day) {
		_tree.sproutLeaves();
	}

	if (SUMMER == _season && 0 == _day) {
		fireSystem->addObject(&(_tree.getLeaves()));
		fireSystem->setEditMode(false);
		fireSystem->onFire(true);
		_tree.catchFire();
	}

	if (AUTUMN == _season && 0 == _day) {
		fireSystem->stopFire();
		_tree.endFire();
		_tree.dropLeaves();
		// start fog
		_sea.startFog();
		_tree.startFog();
		_island.startFog();
		_bottle.startFog();
		_globe.startFog();
	}

	if (AUTUMN == _season && 1 == _day) {
		
	}

	if (WINTER == _season && 0 == _day) {
		_sea.setFrozen(true);
	}
	if (WINTER == _season && 1 == _day)
	{
		_bottle.reset();
		_tree.reset();
		_island.reset();
		_sea.reset();
		_globe.reset();
	}

	////////
	fireSystem->val = glb_Val;

	fireSystem->m_minTriangleArea = glb_minTriangleArea;
	fireSystem->m_maxTriangleArea = glb_maxTriangleArea;
	fireSystem->m_minTriSamples =  glb_minTriSamples;
	fireSystem->m_maxTriSamples =  glb_maxTriSamples;
	
	
	_sea.setWindVector(dir);
	_sea.setWindPower(glb_windPower);
	
	fireSystem->setWindVector(dir);
	fireSystem->setWindPower(glb_windPower);

	_globe.setRadius(glb_WorldRadius);
	_sea.setRadius(glb_WorldRadius);
	
	if (glb_fixedView)
		updateViewMode();

	if (::WINTER == this->_season)
		glb_strSeason = "Winter";
	else if (::SPRING == _season)
		glb_strSeason = "Spring";
	else if (::SUMMER == _season)
		glb_strSeason = "Summer";
	else
		glb_strSeason = "Autumn";
}

void IslandApp::renderScene(float dt) 
{
	bindFrameBuffer();
	resetStates();

	// Set input layout, primitive topology
	g_context()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	g_context()->IASetInputLayout(input_layout);
		
	
	//// Create shadow maps
	for (unsigned int i=0; i<_lights.size(); ++i) 
	{
		_lights[i]->startShadowMapDraw();	
			_lights[i]->drawShadowMap(&_sea);
			_lights[i]->drawShadowMap(&_island);		
			_lights[i]->drawShadowMap(&_tree);
			_lights[i]->drawShadowMap(&_bottle);
		_lights[i]->endShadowMapDraw();
	}


	// Reflections

	// Sea reflections
	_sea.startReflectionDraw(camera, _lights);
		_sea.drawReflection(&_tree);
		_sea.drawReflection(&_tree.getLeaves());
		_sea.drawReflection(&_island);
		_sea.drawReflection(&_bottle);
		_sea.setCullBack(false);
			_sea.drawReflection(&_globe);
		_sea.setCullBack(true);
	_sea.endReflectionDraw(_lights);
	////

	// Sea refractions
	PlanarRefractor* refractor = _sea.getRefractor();
	refractor->setRefractorHeight(_sea.getWorldMatrixVal(3,1));

	refractor->startRefractionDraw(camera, _lights);
		refractor->drawRefraction(&_tree);
		refractor->drawRefraction(&_island);
	refractor->endRefractionDraw(_lights);
	

	// Bottle reflections
	_bottle.startReflectionDraw(camera, _lights);
		_bottle.drawReflection(&_tree);
		_bottle.drawReflection(&_tree.getLeaves());
		_bottle.drawReflection(&_island);
		_bottle.drawReflection(&_sea);
	_bottle.endReflectionDraw();
	//

	
	_island.draw(camera, _lights);
	_tree.draw(camera, _lights);
	_sea.draw(camera, _lights);
	_bottle.draw(camera, _lights);
	
	_sea.drawSpray(camera.getViewMatrix()*camera.getProjectionMatrix(), camera.getPosVector(), dt);
	
	_globe.draw(camera, _lights);
	
	fireSystem->run(dt);
	
	TwDraw();

	// Swap Buffer
	g_swapChain()->Present(0, 0);
}

void IslandApp::updateViewMode()
{
	if (VIEW_GLOBE == m_ViewMode)
	{
		float r = _globe.getRadius();
		XMVECTOR p = -XMVectorSet(0.0f, -0.19f, 0.98f, 1.0f) * (r+5);
		XMFLOAT3 ppos;
		XMStoreFloat3(&ppos, p);
		camera.setPosVector(ppos.x, ppos.y+2.0f, ppos.z);
		
		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.98f, 0.2f);
		camera.setLookVector(0.0f, -0.19f, 0.98f);
	}
	else if (VIEW_TREE == m_ViewMode)
	{
		camera.setPosVector(0.0f, 3.15f, -3.3f);
		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.97f, 0.22f);
		camera.setLookVector(0.0f, -0.22f, 0.97f);
	}
	else if (VIEW_LEAVES == m_ViewMode)
	{
		camera.setPosVector(0.0f, 4.2f, -1.8f);
		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.76f, 0.64f);
		camera.setLookVector(0.0f, -0.64f, 0.76f);
	}
	else if (VIEW_BOTTLE == m_ViewMode)
	{
		camera.setPosVector(-0.47f, 2.5f, -1.29f);
		camera.setRightVector(0.47f, 0.0f, -0.88f);
		camera.setUpVector(0.21f, 0.97f, 0.12f);
		camera.setLookVector(0.85f, -0.25f, 0.46f);
	}
	else	// SEA LEVEL == mode
	{
		float r = _globe.getRadius();
		XMVECTOR p = -XMVectorSet(0.0f, 0.0f, 1.0f, 1.0f) * (r+6);
		XMFLOAT3 ppos;
		XMStoreFloat3(&ppos, p);
		camera.setPosVector(ppos.x, ppos.y+3, ppos.z);

		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.99f, -0.05f);
		camera.setLookVector(0.0f, 0.05f, 0.99f);
	}

}


void IslandApp::onKey(WPARAM key_code)
{
	
	XMFLOAT4 p;
	XMFLOAT4 a = camera.getPosVector();
	XMVECTOR mp;
	XMMATRIX m;
	bool v;
	
	switch (key_code)
	{

		case 27: // ESC
			bEnd = true;
			break;
		case 77: // m
			_tree.changeRenderMode();
			break;

		case 76: // l	
			if (_lights.size() == 1)
			{
				_lights.clear();
				_lights.push_back(&spotlights[1]);
				_lights.push_back(&spotlights[2]);
				_lights.push_back(&spotlights[3]);
				_lights.push_back(&spotlights[0]);
			}
			else
			{
				_lights.clear();
				_lights.push_back(&directional);
			}
			break;

		case 187: // +
			sim_speed += 0.20f;
			break;
		case 189: // -
			sim_speed -= 0.20f;
			sim_speed = max(sim_speed, 0.0f);
			break;
		case 37: // left
			break;
		case 39:	// right
			break;
		case 112 : // F1
			m_ViewMode = VIEW_GLOBE;
			updateViewMode();
			break;

		case 113:  // F2
			m_ViewMode = VIEW_TREE;
			updateViewMode();
			break;

		case 114:	// F3
			m_ViewMode = VIEW_LEAVES;
			updateViewMode();
			break;

		case 115:	// F4
			break;

		case 116:	// F5
			m_ViewMode = VIEW_SEA;
			updateViewMode();
			break;

		case 117:	// F6
			m_ViewMode = VIEW_BOTTLE;
			updateViewMode();

		case WM_MBUTTONUP:
			sim_speed = 1;
			break;

		case 80: // P
			if (g_dev()->GetFeatureLevel() >= D3D_FEATURE_LEVEL_11_0)
				_sea.bSea11 = !_sea.bSea11;
			break; 

		case 81: // Q
			_sea.setFlag(!_sea.getFlag());
			break;

		/////////////////////////////////////////////////////////////

		case 74: // J
			if (sim_speed < 0.001f)
				sim_speed = 1.0f;
			else
				sim_speed = 0.0f;
			break;
		case 75: // K
			v = _tree.PCSS();
			v = !v;
			_tree.setPCSS(v);
			_bottle.setPCSS(v);
			_island.setPCSS(v);
			_sea.setPCSS(v);
			break;

		case 35:	// numpad 1
			p = _lights[0]->getDirection();
			mp = XMLoadFloat4(&p);
			m = XMMatrixRotationX(0.01f);
			mp = XMVector4Transform(mp, m);
			XMStoreFloat4(&p, mp);
			_lights[0]->setDirection(p.x, p.y, p.z);
			break;

		case 34: // numpad 3
			p = _lights[0]->getDirection();
			mp = XMLoadFloat4(&p);
			m = XMMatrixRotationX(-0.01f);
			mp = XMVector4Transform(mp, m);
			XMStoreFloat4(&p, mp);
			_lights[0]->setDirection(p.x, p.y, p.z);
			break;

		case 36:	// numpad 7 
			a.y -= 0.1f;
			camera.setPosVector(a.x, a.y, a.z);
			break;
		case 33:	// numpad 9 - rotate globe
			a.y += 0.1f;
			camera.setPosVector(a.x, a.y, a.z);
			break;
		case 67:	// c
			_lights.clear();
			_lights.push_back(&spotlights[1]);
			_lights.push_back(&spotlights[2]);
			_lights.push_back(&spotlights[3]);
			_lights.push_back(&spotlights[0]);
			break;
			
		case 69: // e
			_lights.clear();
			_lights.push_back(&spotlights[0]);
			break;
		case 82: // r
			_lights.clear();
			_lights.push_back(&spotlights[1]);
			break;
		case 84: // t
			_lights.clear();
			_lights.push_back(&spotlights[2]);
			break;
		case 89: // y
			_lights.clear();
			_lights.push_back(&spotlights[3]);
			break;
		case 86:
			_lights.clear();
			_lights.push_back(&directional);
			break;
		
	}
}

void IslandApp::updateLights(float dt)
{
	XMFLOAT4 p;
	XMFLOAT4 a = camera.getPosVector();
	XMVECTOR mp;
	XMMATRIX m;

	//return;

	float rotation = (dt * 2.0f * 3.14f) / day_length;

	if (Light::LIGHT_SPOT == _lights[0]->type())
	{
	
		// load
		p = directional.getDirection();
		mp = XMLoadFloat4(&p);
	
		// compute
		m = XMMatrixRotationZ(rotation);
		mp = XMVector4Transform(mp, m);
	
		// store
		XMStoreFloat4(&p, mp);
		directional.setDirection(p.x, p.y, p.z);
	}
	else
	{
		// load
		p = _lights[0]->getDirection();
		mp = XMLoadFloat4(&p);
	
		// compute
		m = XMMatrixRotationZ(rotation);
		mp = XMVector4Transform(mp, m);
	
		// store
		XMStoreFloat4(&p, mp);
		_lights[0]->setDirection(p.x, p.y, p.z);
	}
}

void IslandApp::createInputLayout()
{
	
	D3D11_INPUT_ELEMENT_DESC layout[] = {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "NORMAL", 0,  DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TANGENT", 0,  DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEX_COORDS", 0,  DXGI_FORMAT_R32G32_FLOAT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0 }
    };

	D3DX11_PASS_DESC passDesc;
	ID3DX11EffectTechnique* tech;
	tech = fx->GetTechniqueByName("Basic");
	tech->GetPassByIndex(0)->GetDesc(&passDesc);

	HRESULT hr = g_dev()->CreateInputLayout(layout, 4, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &input_layout);
	if (FAILED(hr))
		MessageBoxA(0, "Error creating input layout", 0, 0);

	///////////////////
}

void IslandApp::renderQuad()
{


	UINT stride = sizeof (Vertex);
	UINT offset = 0;

	g_context()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	g_context()->IASetVertexBuffers(0, 1, &vb_quad, &stride, &offset);

	ID3DX11EffectTechnique* tech = fx_quad->GetTechniqueByIndex(0);
	tech->GetPassByIndex(0)->Apply(0, g_context());

	g_context()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

}

void IslandApp::setViewMode(ViewMode mode)
{
	if (VIEW_GLOBE == mode)
	{
		float r = _globe.getRadius();
		XMVECTOR p = -XMVectorSet(0.0f, -0.19f, 0.98f, 1.0f) * (r+6);
		XMFLOAT3 ppos;
		XMStoreFloat3(&ppos, p);
		camera.setPosVector(ppos.x, ppos.y+3.5f, ppos.z);

		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.98f, 0.2f);
		camera.setLookVector(0.0f, -0.19f, 0.98f);
	}
	else if (VIEW_TREE == mode)
	{
		camera.setPosVector(0.0f, 3.15f, -3.3f);
		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.97f, 0.22f);
		camera.setLookVector(0.0f, -0.22f, 0.97f);
	}
	else if (VIEW_LEAVES == mode)
	{
		camera.setPosVector(0.0f, 4.2f, -1.8f);
		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.76f, 0.64f);
		camera.setLookVector(0.0f, -0.64f, 0.76f);
	}
	else if (VIEW_BOTTLE == mode)
	{
		camera.setPosVector(-0.47f, 2.5f, -1.29f);
		camera.setRightVector(0.47f, 0.0f, -0.88f);
		camera.setUpVector(0.21f, 0.97f, 0.12f);
		camera.setLookVector(0.85f, -0.25f, 0.46f);
	}
	else	// SEA LEVEL == mode
	{
		camera.setPosVector(0.0f, 1.56f, -6.4f);
		camera.setRightVector(1.0f, 0.0f, 0.0f);
		camera.setUpVector(0.0f, 0.99f, -0.05f);
		camera.setLookVector(0.0f, 0.05f, 0.99f);
	}
}

void IslandApp::readConfigFile()
{
	string file_config = "../config.txt";

	ifstream fin(file_config, std::ios::in);

	if (!fin)
		MessageBoxA(0, "Could not open config file", 0, 0);

	string token;

	while(!fin.eof())
	{
		fin >> token;

		if (token == "_topX")
			fin >> _params.topX;
		else if (token == "_topY")
			fin >> _params.topY;
		else if (token == "_width") {
			fin >> _params.width;
			setWidth(_params.width);
		}
		else if (token == "_height") {
			fin >> _params.height;
			setHeight(_params.height);
		}
		else if (token == "_globe")
			fin >> _params.file_globe;
		else if (token == "_sea")
			fin >> _params.file_sea;
		else if (token == "_island")
			fin >> _params.file_island;
		else if (token == "_tree")
			fin >> _params.file_tree;
		else if (token == "_bottle")
			fin >> _params.file_bottle;
		else if (token == "_shadow_texture")
			fin >> _params._shadow_texture;
		else if (token == "_day_length")
			fin >> day_length;
		else if (token == "_season_length")
			fin >> season_length;
		else if (token == "_light_start")	
		{
			string light;
			fin >> light;
			
			Light* l;
			float x,y,z;
			int type = Light::LIGHT_SPOT;

			if (light == "directional") {
				l = &directional; 
				type = Light::LIGHT_DIRECTIONAL;
			}
			else if (light == "spot0")
				l = &(spotlights[0]);
			else if (light == "spot1")
				l = &(spotlights[1]);
			else if (light == "spot2")
				l = &(spotlights[2]);
			else if (light == "spot3")
				l = &(spotlights[3]);
			
			l->setType((float)type);

			
			while (token != "_light_end") {

				fin >> token;

				if (token == "_diffuse") {
					fin >> x; fin >> y; fin >> z;
					l->setDiffuse(x,y,z);
				}
					
				else if (token == "_specular") {
					fin >> x; fin >> y; fin >> z;
					l->setSpecular(x,y,z);
				}
					
				else if (token == "_direction") {
					fin >> x; fin >> y; fin >> z;
					l->setDirection(x,y,z);
				}
					
				else if (token == "_position") {
					fin >> x; fin >> y; fin >> z;
					l->setPosition(x,y,z);
				}
					
				else if (token == "_attenuation") {
					fin >> x; fin >> y; fin >> z;
					l->setAttenuation(x,y,z);
				}
					
				else if (token == "_exponent") {
					fin >> x;
					l->setExponent(x);
				}
					
				else if (token == "_cutoff_angle") {
					fin >> x;
					l->setCutOff(x);
				}
			}
		}
	}
}


void IslandApp::onMouseWheel(WPARAM wParam)
{	
	float v = ((signed short)HIWORD(wParam) > 0) ? 0.1f : -0.1f;

	float a = _globe.getRadius();
	float b = _globe.getRadius();

	if (_globe.getRadius() >= 9.0f && v == 0.1f)
		return;

	_globe.setRadius(_globe.getRadius() + v);
	_sea.setRadius(_sea.getRadius() + v);
}


void IslandApp::onLMouseClick(LPARAM lParam)
{
	unsigned y = HIWORD(lParam);
	unsigned x = LOWORD(lParam);
	
	
}

void IslandApp::onRMouseClick(LPARAM lParam)
{
	unsigned y = HIWORD(lParam);
	unsigned x = LOWORD(lParam);

	

}


float g_Angle;
float g_Scale;
TwBar* bar;



std::string strControlsUI[] = { "F1-F6" , "+", "-", "J", "L", "ESC", "WASD + Arrows" };

void IslandApp::initGUI()
{
	ID3D11Device* g = g_dev();
	TwInit(TW_DIRECT3D11, g);


	TwWindowSize(_params.width, _params.height);

	bar = TwNewBar("Desert Island");
	
	TwAddVarRO(bar, "Season: ", TW_TYPE_STDSTRING, &glb_strSeason, "");

	TwAddVarRO(bar, "Change View", TW_TYPE_STDSTRING, &strControlsUI[0], "group=Controls");
	TwAddVarRO(bar, "Increase speed", TW_TYPE_STDSTRING, &strControlsUI[1], "group=Controls");
	TwAddVarRO(bar, "Decrease speed", TW_TYPE_STDSTRING, &strControlsUI[2], "group=Controls");
	TwAddVarRO(bar, "Pause", TW_TYPE_STDSTRING, &strControlsUI[3], "group=Controls");
	TwAddVarRO(bar, "Lighting Mode", TW_TYPE_STDSTRING, &strControlsUI[4], "group=Controls");
	TwAddVarRO(bar, "Exit", TW_TYPE_STDSTRING, &strControlsUI[5], "group=Controls");
	TwAddVarRO(bar, "Camera", TW_TYPE_STDSTRING, &strControlsUI[6], "group=Controls");
	TwAddVarRW(bar, "Fixed Camera", TW_TYPE_BOOL8, &glb_fixedView, "group=Settings");


	TwAddVarRW(bar, "Wind Direction", TW_TYPE_DIR3F, &dir, "group=Settings");
	TwAddVarRW(bar, "Wind Power", TW_TYPE_FLOAT, &glb_windPower, "group=Settings Min=0 Max=1 Step=0.01");
	TwAddVarRW(bar, "World Radius", TW_TYPE_FLOAT, &glb_WorldRadius, "group=Settings Min=5 Max=9 Step=0.05");

}



void IslandApp::onLMouseDrag(int oldX, int oldY, int newX, int newY)
{
	
}